class TG_InterfaceHUD extends HUD;

// The texture which represents the cursor on the screen
var Texture2D CursorTexture;
// The color of the cursor
var const Color CursorColor;
// Cached mouse world origin
var Vector CachedMouseWorldOrigin;
// Cached mouse world direction
var Vector CachedMouseWorldDirection;
// Last mouse interaction interface
var TG_InterfaceInteractionInterface LastMouseInteractionInterface;
// Use ScaleForm?
var bool UsingScaleForm;
// Scaleform mouse movie
var TG_InterfaceGFx TG_InterfaceGFx;


simulated event PostBeginPlay()
{
  Super.PostBeginPlay();

  // If we are using ScaleForm, then create the ScaleForm movie
  if (UsingScaleForm)
  {
    TG_InterfaceGFx = new () class'TG_InterfaceGFx';
    if (TG_InterfaceGFx != None)
    {
      TG_InterfaceGFx.TG_InterfaceHUD = Self;
      TG_InterfaceGFx.SetTimingMode(TM_Game);

     TG_InterfaceGFx.Init(class'Engine'.static.GetEngine().GamePlayers[TG_InterfaceGFx.LocalPlayerOwnerIndex]);
    }
  }
}

simulated event Destroyed()
{
  Super.Destroyed();
  
  // If the ScaleForm movie exists, then destroy it
  if (TG_InterfaceGFx != None)
  {
    TG_InterfaceGFx.Close(true);
    TG_InterfaceGFx = None;
  }
}

function PreCalcValues()
{
  Super.PreCalcValues();

  // If the ScaleForm movie exists, then reset it's viewport, scale mode and alignment to match the
  // screen resolution
  if (TG_InterfaceGFx != None)
  {
    TG_InterfaceGFx.SetViewport(0, 0, SizeX, SizeY);
    TG_InterfaceGFx.SetViewScaleMode(SM_NoScale);
    TG_InterfaceGFx.SetAlignment(Align_TopLeft);  
  }
}

/*simulated function SwitchCursorTexture(Texture2D Cursor)
{
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
 // Ensure that we aren't using ScaleForm and that we have a valid cursor
  if (!UsingScaleForm && CursorTexture != None)
  {
    // Ensure that we have a valid PlayerOwner
    if (PlayerOwner != None)
    {
      // If we're not using scale form and we have a valid cursor texture, render it
      if (MouseInterfacePlayerInput != None)
      {
        Canvas.DrawTile(Cursor, CursorTexture.SizeX, CursorTexture.SizeY, 0.f, 0.f, CursorTexture.SizeX, CursorTexture.SizeY,, true);
      }
    }
  }
}       */
event PostRender()
{
  local TG_InterfacePlayerInput TG_InterfacePlayerInput;
  local TG_InterfaceInteractionInterface TG_InteractionInterface;
  local Vector HitLocation, HitNormal;

  Super.PostRender();

  // Ensure that we aren't using ScaleForm and that we have a valid cursor
  if (!UsingScaleForm && CursorTexture != None)
  {
    // Ensure that we have a valid PlayerOwner
    if (PlayerOwner != None)
    {
      // Cast to get the MouseInterfacePlayerInput
      TG_InterfacePlayerInput = TG_InterfacePlayerInput(PlayerOwner.PlayerInput)  ;

      // If we're not using scale form and we have a valid cursor texture, render it
      if (TG_InterfacePlayerInput != None)
      {
        // Set the canvas position to the mouse position
        Canvas.SetPos(TG_InterfacePlayerInput.MousePosition.X, TG_InterfacePlayerInput.MousePosition.Y);
        // Set the cursor color
        Canvas.DrawColor = CursorColor;
        // Draw the texture on the screen
        Canvas.DrawTile(CursorTexture, CursorTexture.SizeX, CursorTexture.SizeY, 0.f, 0.f, CursorTexture.SizeX, CursorTexture.SizeY,, true);
      }
    }
  }

  // Get the current mouse interaction interface
  TG_InteractionInterface = GetMouseActor(HitLocation, HitNormal);

  // Handle mouse over and mouse out
  // Did we previously had a mouse interaction interface?
  if (LastMouseInteractionInterface != None)
  {
    // If the last mouse interaction interface differs to the current mouse interaction
    if (LastMouseInteractionInterface != TG_InteractionInterface)
    {
      // Call the mouse out function
      LastMouseInteractionInterface.MouseOut(CachedMouseWorldOrigin, CachedMouseWorldDirection);
      // Assign the new mouse interaction interface
      LastMouseInteractionInterface = TG_InteractionInterface; 

      // If the last mouse interaction interface is not none
      if (LastMouseInteractionInterface != None)
      {
        // Call the mouse over function
        LastMouseInteractionInterface.MouseOver(CachedMouseWorldOrigin, CachedMouseWorldDirection); // Call mouse over
      }
    }
  }
  else if (TG_InteractionInterface != None)
  {
    // Assign the new mouse interaction interface
    LastMouseInteractionInterface = TG_InteractionInterface; 
    // Call the mouse over function
    LastMouseInteractionInterface.MouseOver(CachedMouseWorldOrigin, CachedMouseWorldDirection); 
  }
  }

function TG_InterfaceInteractionInterface GetMouseActor(optional out Vector HitLocation, optional out Vector HitNormal)
{
  local TG_InterfaceInteractionInterface TG_InteractionInterface;
  local TG_InterfacePlayerInput TG_InterfacePlayerInput;
  local Vector2D MousePosition;
  local Actor HitActor;

  // Ensure that we have a valid canvas and player owner
  if (Canvas == None || PlayerOwner == None)
  {
    return None;
  }

  // Type cast to get the new player input
  TG_InterfacePlayerInput = TG_InterfacePlayerInput(PlayerOwner.PlayerInput)  ;

  // Ensure that the player input is valid
  if (TG_InterfacePlayerInput == None)
  {
    return None;
  }

  // We stored the mouse position as an IntPoint, but it's needed as a Vector2D
  MousePosition.X = TG_InterfacePlayerInput.MousePosition.X;
  MousePosition.Y = TG_InterfacePlayerInput.MousePosition.Y;
  // Deproject the mouse position and store it in the cached vectors
  Canvas.DeProject(MousePosition, CachedMouseWorldOrigin, CachedMouseWorldDirection);

  // Perform a trace actor interator. An interator is used so that we get the top most mouse interaction
  // interface. This covers cases when other traceable objects (such as static meshes) are above mouse
  // interaction interfaces.
  ForEach TraceActors(class'Actor', HitActor, HitLocation, HitNormal, CachedMouseWorldOrigin + CachedMouseWorldDirection * 65536.f, CachedMouseWorldOrigin,,, TRACEFLAG_Bullet)
  {
    // Type cast to see if the HitActor implements that mouse interaction interface
    TG_InteractionInterface = TG_InterfaceInteractionInterface(HitActor);
    if (TG_InteractionInterface != None)
    {
      return TG_InteractionInterface;
    }
  }

  return None;
}

function Vector GetMouseWorldLocation()
{
  local TG_InterfacePlayerInput TG_InterfacePlayerInput;
  local Vector2D MousePosition;
  local Vector MouseWorldOrigin, MouseWorldDirection, HitLocation, HitNormal;

  // Ensure that we have a valid canvas and player owner
  if (Canvas == None || PlayerOwner == None)
  {
    return Vect(0, 0, 0);
  }

  // Type cast to get the new player input
  TG_InterfacePlayerInput = TG_InterfacePlayerInput(PlayerOwner.PlayerInput)  ;

  // Ensure that the player input is valid
  if (TG_InterfacePlayerInput == None)
  {
    return Vect(0, 0, 0);
  }

  // We stored the mouse position as an IntPoint, but it's needed as a Vector2D
  MousePosition.X = TG_InterfacePlayerInput.MousePosition.X;
  MousePosition.Y = TG_InterfacePlayerInput.MousePosition.Y;
  // Deproject the mouse position and store it in the cached vectors
  Canvas.DeProject(MousePosition, MouseWorldOrigin, MouseWorldDirection);

  // Perform a trace to get the actual mouse world location.
  Trace(HitLocation, HitNormal, MouseWorldOrigin + MouseWorldDirection * 65536.f, MouseWorldOrigin , true,,, TRACEFLAG_Bullet);
  return HitLocation;
}

defaultproperties
{
  // Set to false if you wish to use Unreal's player input to retrieve the mouse coordinates
  UsingScaleForm=false
  CursorColor=(R=255,G=255,B=255,A=255)
  CursorTexture=Texture2D'EngineResources.Cursors.Arrow'
}